package com.openroom.ui;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.Bindable;
import org.apache.pivot.collections.Map;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.collections.Sequence.Tree.Path;
import org.apache.pivot.util.Resources;
import org.apache.pivot.util.Vote;
import org.apache.pivot.util.concurrent.Task;
import org.apache.pivot.util.concurrent.TaskExecutionException;
import org.apache.pivot.util.concurrent.TaskListener;
import org.apache.pivot.wtk.Action;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.ButtonPressListener;
import org.apache.pivot.wtk.CardPane;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.FileBrowserSheet;
import org.apache.pivot.wtk.Label;
import org.apache.pivot.wtk.LinkButton;
import org.apache.pivot.wtk.MenuBar;
import org.apache.pivot.wtk.Meter;
import org.apache.pivot.wtk.PushButton;
import org.apache.pivot.wtk.Sheet;
import org.apache.pivot.wtk.SheetCloseListener;
import org.apache.pivot.wtk.SplitPane;
import org.apache.pivot.wtk.TabPane;
import org.apache.pivot.wtk.TabPaneSelectionListener;
import org.apache.pivot.wtk.TextInput;
import org.apache.pivot.wtk.Window;

import com.jphotomanager.io.ImageImporter;
import com.openroom.db.DBHelper;
import com.openroom.event.ApplicationEvent;
import com.openroom.event.EventHandler;
import com.openroom.event.EventManager;
import com.openroom.event.EventType;
import com.openroom.model.Catalog;
import com.openroom.model.Folder;
import com.openroom.model.ModelLocator;
import com.openroom.model.ModelLocator.ModeFlag.ImageViewMode;
import com.openroom.model.ModelLocator.ModeFlag.NavigationMode;
import com.openroom.model.Photograph;
import com.openroom.ui.action.AutoWBAction;
import com.openroom.ui.action.CropAction;
import com.openroom.ui.action.ImportAction;
import com.openroom.ui.action.ImportFolderAction;
import com.openroom.ui.action.RotateAction;
import com.openroom.ui.component.CatalogTreeView;
import com.openroom.ui.component.FilterPanel;
import com.openroom.ui.component.FolderTreeView;
import com.openroom.ui.component.FullViewImage;
import com.openroom.ui.component.PreviewImagePane;
import com.openroom.ui.component.PreviewNavContainer;
import com.openroom.ui.component.ThumbnailPanel;
import com.openroom.ui.component.ThumbnailPreviewPane;
import com.openroom.ui.component.TnailStrip;

public class MainWindow extends Window implements Bindable {

    private static final Logger LOGGER = Logger
            .getLogger(MainWindow.ExportAction.class);

    private final class ExportAction extends Action {

        private boolean exportOriginal = false;

        public ExportAction(boolean exportOriginal) {
            super();
            this.exportOriginal = exportOriginal;
        }

        @Override
        public void perform(Component source) {
            fileBrowserSheet
                    .setMode(org.apache.pivot.wtk.FileBrowserSheet.Mode.SAVE_TO);
            fileBrowserSheet.open(MainWindow.this, new SheetCloseListener() {
                @Override
                public void sheetClosed(Sheet sheet) {
                    Sequence<File> selectedFiles = fileBrowserSheet
                            .getSelectedFiles();
                    if (selectedFiles.getLength() == 1) {
                        File file = selectedFiles.get(0);
                        if (file.isDirectory()) {
                            Photograph photograph = ModelLocator.getInstance()
                                    .getCurrentlySelectedImage();
                            try {
                                if (exportOriginal) {
                                    FileUtils.copyFile(
                                            new File(photograph
                                                    .getRawFilePath()),
                                            new File(file, photograph
                                                    .getFileName()));
                                } else {
                                    FileUtils.copyFile(
                                            new File(photograph
                                                    .getPreviewImagePath()),
                                            new File(file, photograph
                                                    .getFileName()));
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
        }
    }

    private final class PreviewTabPaneSelectionListener implements
            TabPaneSelectionListener {
        @Override
        public Vote previewSelectedIndexChange(TabPane tabPane,
                int selectedIndex) {
            return Vote.APPROVE;
        }

        @Override
        public void selectedIndexChangeVetoed(TabPane tabPane, Vote reason) {

        }

        @Override
        public void selectedIndexChanged(TabPane tabPane,
                int previousSelectedIndex) {
            if (tabPane.getSelectedIndex() == 1) {
                ModelLocator.getInstance().setCurrentImageMode(
                        ImageViewMode.PREVIEW);
            } else {
                ModelLocator.getInstance().setCurrentImageMode(
                        ImageViewMode.THUMBNAIL);
            }
        }
    }

    public static String TEMP_DIR = "/home/home/tnails/";

    @BXML
    ThumbnailPanel tnailGrid = null;

    MenuBar menuBar = null;

    @BXML
    FileBrowserSheet fileBrowserSheet;

    @BXML
    static FolderTreeView folderTree;

    @BXML
    ThumbnailPreviewPane thumbnailPreviewPane;

    @BXML
    CatalogTreeView catalogTree;

    @BXML
    TabPane previewPane;

    @BXML
    Sheet dialog;

    @BXML
    Sheet importDialog;

    @BXML
    Meter meter;

    @BXML
    PreviewImageView previewImage;

    @BXML
    FullViewImage fullImage;

    @BXML
    CardPane cardPane;

    @BXML
    LinkButton fullButton;

    @BXML
    LinkButton previewButton;
    @BXML
    LinkButton twoStarBtn;
    @BXML
    LinkButton oneStarBtn;
    @BXML
    LinkButton threeStarBtn;
    @BXML
    LinkButton fourStarBtn;
    @BXML
    LinkButton rejectTnailBtn;

    @BXML
    LinkButton oneStarTnailFilterBtn;
    @BXML
    LinkButton twoStarTnailFilterBtn;
    @BXML
    LinkButton threeStarTnailFilterBtn;
    @BXML
    LinkButton fourStarTnailFilterBtn;
    @BXML
    LinkButton fiveStarTnailFilterBtn;

    @BXML
    LinkButton fiveStarBtn;

    @BXML
    TabPane leftTabPane;

    @BXML
    SplitPane splitPane;

    @BXML
    Label importStatusLabel;

    @BXML
    LinkButton oneStarTnailBtn;
    @BXML
    LinkButton twoStarTnailBtn;
    @BXML
    LinkButton threeStarTnailBtn;
    @BXML
    LinkButton fourStarTnailBtn;
    @BXML
    LinkButton fiveStarTnailBtn;

    @BXML
    PreviewImagePane previewImagePane;

    @BXML
    TextInput folderPathToImport;

    @BXML
    private Sheet feedbackDialog;

    @BXML
    private FilterPanel filter;

    private ImportAction importAction;

    private ImportFolderAction importFolderAction;

    @BXML
    private PreviewNavContainer previewNavBar;

    private PreviewMakingTask task;

    @BXML
    private PushButton cancelTask;

    @BXML
    private TnailStrip tnailStrip;

    public MainWindow() {
        importAction = new ImportAction();
        importFolderAction = new ImportFolderAction();
        Action.getNamedActions().put("crop", new CropAction());
        Action.getNamedActions().put("rotate_right",
                new RotateAction(EventType.ROTATE_RIGHT));
        Action.getNamedActions().put("rotate_left",
                new RotateAction(EventType.ROTATE_LEFT));
        Action.getNamedActions().put("flip_horizontal",
                new RotateAction(EventType.FLIP_HORIZONTAL));
        Action.getNamedActions().put("flip_vertical",
                new RotateAction(EventType.FLIP_VERTICAL));
        Action.getNamedActions().put("revert_to_original",
                new RotateAction(EventType.REVERT_TO_ORIGINAL));
        Action.getNamedActions().put("AutoWB", new AutoWBAction());
        Action.getNamedActions().put("DeleteFolder", new Action() {
            @Override
            public void perform(Component arg0) {
                ModelLocator.getInstance().deleteCurrentFolder();
            }

        });
        Action.getNamedActions().put("ExportImage", new ExportAction(true));
        Action.getNamedActions().put("ExportPreview", new ExportAction(false));
        Action.getNamedActions().put("DeleteRejected", new Action() {
            @Override
            public void perform(Component arg0) {
                ImageImporter.deleteAllRejected();
            }

        });
        Action.getNamedActions().put("GeneratePreview", new Action() {
            @Override
            public void perform(Component arg0) {
                dialog.open(MainWindow.this);
                task = new PreviewMakingTask(meter, importStatusLabel,
                        ModelLocator.getInstance().getCurrentlySelectedFolder());
                task.execute(new TaskListener<Void>() {

                    @Override
                    public void executeFailed(Task<Void> arg0) {
                        dialog.close();
                    }

                    @Override
                    public void taskExecuted(Task<Void> arg0) {
                        dialog.close();
                    }
                });
            }
        });
    }

    @Override
    public void initialize(Map<String, Object> namespace, URL arg1,
            Resources arg2) {
        folderTree.initialize(namespace, arg1, arg2, this);
        importAction.initialize(namespace, arg1, arg2, this);
        importFolderAction.initialize(namespace, arg1, arg2, this);
        filter.initialize(namespace, arg1, arg2, this);

        previewButton.getButtonPressListeners().add(new ButtonPressListener() {
            @Override
            public void buttonPressed(org.apache.pivot.wtk.Button button) {
                cardPane.setSelectedIndex(0);
            }
        });
        new RatingComponent(oneStarBtn, twoStarBtn, threeStarBtn, fourStarBtn,
                fiveStarBtn).initialize();
        new RatingComponent(oneStarTnailBtn, twoStarTnailBtn,
                threeStarTnailBtn, fourStarTnailBtn, fiveStarTnailBtn)
                .initialize();
        previewPane.getTabPaneSelectionListeners().add(
                new PreviewTabPaneSelectionListener());

        initializeTabPanes();
        catalogTree.initialize(namespace, arg1, arg2, this);
        new LeftNavComponent(this).initialize();
        previewImagePane.initialize(namespace, arg1, arg2);
        thumbnailPreviewPane.initialize(namespace, arg1, arg2);
        Task<Void> loadTsk = new Task<Void>() {

            @Override
            public Void execute() throws TaskExecutionException {
                loadSavedDB();
                return null;
            }
        };
        loadTsk.execute(new TaskListener<Void>() {

            @Override
            public void taskExecuted(Task<Void> task) {
                // TODO Auto-generated method stub

            }

            @Override
            public void executeFailed(Task<Void> task) {
                // TODO Auto-generated method stub

            }
        });

        EventManager.getInstance().listenToEventType(new EventHandler() {

            @Override
            public void handle(ApplicationEvent event) {
                previewPane.setSelectedIndex(0);
            }
        }, EventType.CURRENT_FOLDER_CHANGED, EventType.CURRENT_CATALOG_CHANGED);
        previewNavBar.initialize(namespace, arg1, arg2, this);
        cancelTask.getButtonPressListeners().add(new ButtonPressListener() {

            @Override
            public void buttonPressed(Button button) {
                System.out.println("Aborting the task");
                importAction.abortImport();
                if (task != null)
                    task.abort();
                importFolderAction.abortImport();
            }
        });
        tnailStrip.initialize(namespace, arg1, arg2, this);
        EventManager.getInstance().publishEvent(
                new ApplicationEvent(EventType.INITIALIZATION_COMPLETE));
    }

    public static void loadSavedDB() {
        long start = System.nanoTime();
        List<Folder> getallImportedFolders = DBHelper.getInstance()
                .getallImportedFolders();
        ModelLocator.getInstance().setAllFolders(getallImportedFolders);
        List<Catalog> allCatalogs = DBHelper.getInstance().getAllCatalogs();
        ModelLocator.getInstance().setAllCatalogs(allCatalogs);
        if (ModelLocator.getInstance().getCurrentlySelectedFolder() == null) {
            folderTree.setSelectedPath(new Path(0));
        }
        long end = System.nanoTime();
        LOGGER.info("MainWindow.loadSavedDB() finished in " + (end - start)
                / 1000 + " ms");
    }

    private void initializeTabPanes() {
        leftTabPane.getTabPaneSelectionListeners().add(
                new TabPaneSelectionListener() {

                    @Override
                    public Vote previewSelectedIndexChange(TabPane tabPane,
                            int selectedIndex) {
                        return Vote.APPROVE;
                    }

                    @Override
                    public void selectedIndexChangeVetoed(TabPane tabPane,
                            Vote reason) {

                    }

                    @Override
                    public void selectedIndexChanged(TabPane tabPane,
                            int previousSelectedIndex) {
                        if (tabPane.getSelectedIndex() == -1) {
                            splitPane.setSplitRatio(new Float(0.02));
                        } else {
                            splitPane.setSplitRatio(new Float(0.15));
                        }
                        switch (tabPane.getSelectedIndex()) {
                        case 0:
                            ModelLocator.getInstance().setNavigationMode(
                                    NavigationMode.CATALOG);
                            break;
                        case 1:
                            ModelLocator.getInstance().setNavigationMode(
                                    NavigationMode.FOLDER);
                            break;
                        default:
                            break;
                        }
                    }

                });
    }

}
